<?php
	/* Functions in this file */
	/**************************/

	// ClearFormulaFlag($flag)
	// ClearFormulaModificationFlag($flag)
	// ClearFormulaModifications()
	// GetFormula()
	// GetFormulaModificationsCount()
	// GetFretPosition()
	// GetMFCClassName()
	// GetMFCClassSchema()
	// GetType()
	// HasBrackets()
	// IsFormulaFlagSet($flag)
	// IsFormulaModificationFlagSet($flag)
	// IsFretPositionUsed()
	// IsNoChord()
	// IsTypeUsed()
	// IsValidFormula($formula)
	// IsValidFormulaFlag($flag)
	// IsValidFretPosition($fretPosition)
	// IsValidKey($key)
	// IsValidKeyVariation($keyVariation)
	// IsValidType($type)
	// SetFormula($formula)
	// SetFormulaFlag($flag)
	// SetFormulaModificationFlag($flag)
	// SetFormulaModifications($formulaModifications)
	// SetFretPosition($fretPosition)
	// SetType($type)
?>
<?php
	 
	class ChordName {
		 
		 
		// Default Constants
		const DEFAULT_KEY = 0x00001010; // self::C/C
		const DEFAULT_FORMULA = 0x00000000;
		// Major
		const DEFAULT_FORMULA_MODIFICATIONS = 0;
		const DEFAULT_EXTRA = 0;
		 
		// Type Constants
		const MIN_TYPE = 2;
		const MAX_TYPE = 8;
		 
		// Fret Position Constants
		const MIN_FRET_POSITION = 0;
		const MAX_FRET_POSITION = 24;
		 
		 
		const C = 0x00000000;
		const CSharp = 0x00000001;
		const D = 0x00000002;
		const EFlat = 0x00000003;
		const E = 0x00000004;
		const F = 0x00000005;
		const FSharp = 0x00000006;
		const G = 0x00000007;
		const AFlat = 0x00000008;
		const A = 0x00000009;
		const BFlat = 0x0000000a;
		const B = 0x0000000b;
		 
		 
		// Key variations (homonyms)
		 
		const variationDown = 0x00000000;
		const variationDefault = 0x00000001;
		const variationUp = 0x00000002;
		 
		 
		 
		const tonicKeyMask = 0x00000f00;
		const tonicKeyVariationMask = 0x00003000;
		const tonicKeyAndVariationMask = 0x00003f00;
		const bassNoteKeyMask = 0x0000000f;
		const bassNoteKeyVariationMask = 0x00000030;
		const bassNoteKeyAndVariationMask = 0x0000003f;
		 
		 
		 
		const noChord = 0x00000010;
		const brackets = 0x00000020;
		const bassNoteSharps = 0x00000040;
		const tonicSharps = 0x00000080;
		const formulaFlagsMask = 0x000000f0;
		const formulaMask = 0x0000000f;
		 
		 
		 
		const major = 0x00000000;
		const minor = 0x00000001;
		const augmented = 0x00000002;
		const diminished = 0x00000003;
		const powerChord = 0x00000004;
		const major6th = 0x00000005;
		const minor6th = 0x00000006;
		const dominant7th = 0x00000007;
		const major7th = 0x00000008;
		const minor7th = 0x00000009;
		const augmented7th = 0x0000000a;
		const diminished7th = 0x0000000b;
		const minorMajor7th = 0x0000000c;
		const minor7thFlatted5th = 0x0000000d;
		 
		 
		 
		const extended9th = 0x00000001;
		const extended11th = 0x00000002;
		const extended13th = 0x00000004;
		const added2nd = 0x00000008;
		const added4th = 0x00000010;
		const added6th = 0x00000020;
		const added9th = 0x00000040;
		const added11th = 0x00000080;
		const flatted5th = 0x00000100;
		const raised5th = 0x00000200;
		const flatted9th = 0x00000400;
		const raised9th = 0x00000800;
		const raised11th = 0x00001000;
		const flatted13th = 0x00002000;
		const suspended2nd = 0x00004000;
		const suspended4th = 0x00008000;
		 
		 
		 
		const fretPositionNotUsed = 0x000000ff;
		const fretPositionMask = 0x0000001f;
		const typeNotUsed = 0x000000ff;
		const typeMask = 0x000000e0;
		 
		 
		 
		protected $m_key = self::DEFAULT_KEY;
		protected $m_formula = self::DEFAULT_FORMULA;
		protected $m_formulaModifications = self::DEFAULT_FORMULA_MODIFICATIONS;
		protected $m_extra = self::DEFAULT_EXTRA;
		 
		 
		// MFC Class Functions
		 
		 
		function GetMFCClassName() {
			return "CChordName";
		}
		 
		 
		function GetMFCClassSchema() {
			return 1;
		}
		 
		// Key Functions
		 
		 
		 
		function IsValidKey($key) {
			return ($key <= self::B);
		}
		 
		 
		 
		function IsValidKeyVariation($keyVariation) {
			return ($keyVariation <= self::variationUp);
		}
		 
		 
		 
		 
		function IsValidKeyAndVariation($key, $keyVariation) {
			return ((self::IsValidKey($key) && self::IsValidKeyVariation($keyVariation)) && !($key == self::AFlat && $keyVariation == self::variationUp));
		}
		 
		 
		 
		function IsValidFormula($formula) {
			return ($formula <= self::minor7thFlatted5th);
		}
		 
		 
		function SetBrackets($set = 1) {
			if (!$set) return ($this->ClearFormulaFlag(self::brackets));
				 return ($this->SetFormulaFlag(self::brackets));
		}
		 
		 
		function HasBrackets() {
			return ($this->IsFormulaFlagSet(self::brackets));
		}
		 
		 
		function SetNoChord($set = 1) {
			if (!$set) return ($this->ClearFormulaFlag(self::noChord));
				 return ($this->SetFormulaFlag(self::noChord));
		}
		 
		 
		function IsNoChord() {
			return ($this->IsFormulaFlagSet(self::noChord));
		}
		 
		// Formula Flag Functions
		 
		 
		 
		 
		function IsValidFormulaFlag($flag) {
			return ((($flag & self::formulaFlagsMask) != 0) && (($flag & ~self::formulaFlagsMask) == 0));
		}
		 
		 
		 
		function SetFormulaFlag($flag) {
			if (!$this->IsValidFormulaFlag($flag)) return 0;
			$this->m_key |= $flag;
			 return 1;
		}
		 
		 
		 
		function ClearFormulaFlag($flag) {
			if (!$this->IsValidFormulaFlag($flag)) return 0;
			$this->m_key &= ~$flag;
			 return 1;
		}
		 
		 
		 
		function IsFormulaFlagSet($flag) {
			return (($this->m_key & $flag) == $flag);
		}
		 
		// Formula Modifications Functions
		 
		 
		function SetFormulaModifications($formulaModifications) {
			$this->m_formulaModifications = $formulaModifications;
		}
		 
		function ClearFormulaModifications() {
			$this->m_formulaModifications = 0;
		}
		 
		 
		 
		function IsFormulaModificationFlagSet($flag) {
			return (($this->m_formulaModifications & $flag) == $flag);
		}
		 
		 
		 
		function SetFormulaModificationFlag($flag) {
			$this->m_formulaModifications |= $flag;
		}
		 
		 
		function ClearFormulaModificationFlag($flag) {
			$this->m_formulaModifications &= ~$flag;
		}
		 
		 
		 
		function IsValidFretPosition($fretPosition) {
			return ((($fretPosition >= self::MIN_FRET_POSITION) && ($fretPosition <= self::MAX_FRET_POSITION)) || ($fretPosition == self::fretPositionNotUsed));
		}
		 
		 
		function IsFretPositionUsed() {
			return ($this->GetFretPosition() != self::fretPositionNotUsed);
		}
		 
		// Type Functions
		 
		 
		 
		function IsValidType($type) {
			return ((($type >= self::MIN_TYPE) && ($type <= self::MAX_TYPE)) || ($type == self::typeNotUsed));
		}
		 
		 
		function IsTypeUsed() {
			return ($this->GetType() != self::typeNotUsed);
		}
		 
		 
		 
		 
		function ChordName($tonicKey = NULL, $tonicKeyVariation = NULL, $formula = NULL, $formulaModifications = NULL, $fretPosition = NULL, $type = NULL) {
			 
			
			$this->SetTonic($tonicKey, $tonicKeyVariation);
			$this->SetFormula($formula);
			$this->SetFormulaModifications($formulaModifications);
			$this->SetFretPosition($fretPosition);
			$this->SetType($type);
		}
		 
		
		// Serialize Functions
		 
		function DoSerialize(&$stream){
		 
			WRITE_WORD ($stream,$this->m_key);
			WRITE_BYTE ($stream,$this->m_formula);
			WRITE_WORD ($stream,$this->m_formulaModifications);
			WRITE_BYTE ($stream,$this->m_extra);

			return 1;
		}
		
		 
		function DoDeserialize(&$stream){
		 
		
			$this->m_key = READ_WORD ($stream);
			$this->m_formula = READ_BYTE ($stream);
			$this->m_formulaModifications = READ_WORD ($stream);
			$this->m_extra = READ_BYTE ($stream);
		
		}
		
		 
		// Tonic Functions
		 
		 
		 
		 
		function SetTonic($key, $keyVariation) {
			 
			//------Last Checked------//
			// - Jan 17, 2005
			if (!$this->IsValidKeyAndVariation($key, $keyVariation)) return 0;
			 
			$this->m_key &= ~self::tonicKeyAndVariationMask;
			 
			$this->m_key |= ($key << 8);
			$this->m_key |= ($keyVariation << 12);
			 
			return 1;
		}
		 
		 
		 
		 
		function GetTonic(&$key, &$keyVariation) {
			 
			//------Last Checked------//
			// - Jan 17, 2005
			$key = (($this->m_key & self::tonicKeyMask) >> 8);
			$keyVariation = (($this->m_key & self::tonicKeyVariationMask) >> 12);
		}
		 
		 
		 
		 
		 
		function IsSameTonic($key, $keyVariation) {
			 
			//------Last Checked------//
			// - Jan 17, 2005
			$thisKey = 0;
			$thisKeyVariation = 0;
			$this->GetTonic($thisKey, $thisKeyVariation);
			return (($thisKey == $key) && ($thisKeyVariation == $keyVariation));
		}
		 
		// Bass Note Functions
		 
		 
		 
		 
		function SetBassNote($key, $keyVariation) {
			 
			//------Last Checked------//
			// - Jan 17, 2005
			if (!$this->IsValidKeyAndVariation($key, $keyVariation)) return 0;
			 
			$this->m_key &= ~self::bassNoteKeyAndVariationMask;
			 
			$this->m_key |= $key;
			$this->m_key |= ($keyVariation << 4);
			 
			return 1;
		}
		 
		 
		 
		 
		function GetBassNote(&$key, &$keyVariation) {
			 
			//------Last Checked------//
			// - Jan 17, 2005
			$key = ($this->m_key & self::bassNoteKeyMask);
			$keyVariation = (($this->m_key & self::bassNoteKeyVariationMask) >> 4);
		}
		 
		 
		 
		 
		 
		function IsSameBassNote($key, $keyVariation) {
			 
			//------Last Checked------//
			// - Jan 17, 2005
			$thisKey = 0;
			$thisKeyVariation = 0;
			$this->GetBassNote($thisKey, $thisKeyVariation);
			return (($thisKey == $key) && ($thisKeyVariation == $keyVariation));
		}
		 
		// Formula Functions
		 
		 
		 
		function SetFormula($formula) {
			 
			//------Last Checked------//
			// - Jan 4, 2005
			if (!$this->IsValidFormula($formula)) return 0;
			 
			$this->m_formula &= ~self::formulaMask;
			$this->m_formula |= $formula;
			return 1;
		}
		 
		 
		 
		function GetFormula() {
			 
			//------Last Checked------//
			// - Jan 4, 2005
			return (($this->m_formula & self::formulaMask));
		}
		 
		// Formula Modifications Functions
		 
		 
		function GetFormulaModificationsCount() {
			 
			//------Last Checked------//
			// - Jan 4, 2005
			$returnValue = 0;
			 
			$i = self::extended9th;
			for (; $i <= self::suspended4th; $i = 2 * $i) {
				 
				if ($this->IsFormulaModificationFlagSet($i))
					$returnValue++;
				 
				// Wraparound break
				if ($i == self::suspended4th)
					break;
			}
			 
			return ($returnValue);
		}
		 
		// Fret Position Functions
		 
		 
		 
		function SetFretPosition($fretPosition) {
			 
			//------Last Checked------//
			// - Jan 4, 2005
			if (!$this->IsValidFretPosition($fretPosition)) return 0;
			 
			// Note: Fret position is stored as values 0 to 31; 0 = not used, 1 to 31 = open to 30th fret
			if ($fretPosition == self::fretPositionNotUsed)
				$fretPosition = 0;
			else
				$fretPosition++;
			 
			$this->m_extra &= ~self::fretPositionMask;
			$this->m_extra |= $fretPosition;
			 
			return 1;
		}
		 
		 
		 
		function GetFretPosition() {
			 
			//------Last Checked------//
			// - Jan 4, 2005
			$returnValue = ($this->m_extra & self::fretPositionMask);
			return (($returnValue == 0) ? self::fretPositionNotUsed : ($returnValue - 1));
		}
		 
		// Type Functions
		 
		 
		 
		function SetType($type) {
			 
			//------Last Checked------//
			// - Jan 4, 2005
			if (!$this->IsValidType($type)) return 0;
			 
			// Note: Type is stored as values 0 to 7; 0 = not used, 1 to 7 = $types 2 to 8
			if ($type == self::typeNotUsed)
				$type = 0;
			else
				$type--;
			 
			$this->m_extra &= ~self::typeMask;
			$this->m_extra |= ($type << 5);
			return 1;
		}
		 
		 
		 
		function GetType() {
			 
			//------Last Checked------//
			// - Jan 4, 2005
			$returnValue = ($this->m_extra >> 5);
			return (($returnValue == 0) ? self::typeNotUsed : ($returnValue + 1));
		}
		 
		 
	}
	 
?>

